﻿using System;
using System.Runtime.Serialization;

namespace Ns
{
    /// <summary>
    /// Represents a <see cref="Recurrence"/> executed after each elapsed <see cref="Period"/> of time.
    /// This class cannot be inherited.
    /// </summary>
    [Serializable]
    [DataContract]
    public sealed class PeriodRecurrence : Recurrence
    {
        #region Properties

        /// <summary>
        /// Gets the recurrence period (ex: every 2 hours).
        /// </summary>
        [DataMember(EmitDefaultValue = false)]
        public TimeSpan Period { get; internal set; }

        #endregion

        #region Methods

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return string.Format("Occurs every {0}"
                , Period);
        }

        /// <summary>
        /// Clones this instance.
        /// </summary>
        /// <returns>A copy of this instance.</returns>
        public override object Clone()
        {
            return new PeriodRecurrence(Period);
        }

        /// <summary>
        /// Gets the date and time of the next occurrence from <paramref name="now"/>.
        /// </summary>
        /// <param name="now">The current date and time assumed to be an universal time if not specified to avoid ambiguous dates.</param>
        /// <returns>The date and time of the next occurrence in local time.</returns>
        protected override DateTime GetNextDateTime(DateTime now)
        {
            return now.AsUniversalTime().ToUniversalTime().Add(Period).ToLocalTime();
        }

        #endregion

        #region Constructors

        private PeriodRecurrence()
        {
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="PeriodRecurrence"/> class 
        /// with the specified <paramref name="period"/> between each occurrence.
        /// </summary>
        /// <param name="period">The time interval between each occurrence.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="period"/> is not strictly positive.
        /// </exception>
        public PeriodRecurrence(TimeSpan period)
        {
            if (period <= TimeSpan.Zero)
                throw new ArgumentOutOfRangeException("period");

            Period = period;
        }

        #endregion
    }
}